using System;
using System.Collections.Generic;
using System.Text;

using Microsoft.Xna.Framework;
using CreamX.Framework.Attributes;


namespace CreamX.Framework.Game.Components
{
    [CreamXComponentAttribute("CreamXTileGridComponent")]
    public class CreamXTileGridComponent:CreamXComponent
    {
        
        //internal List<Tile> _tiles;
        
        private int _tileCountX;
        private int _tileCountY;
        private int _tileCutSizeX;
        private int _tileCutSizeY;
        private int _tileDisplaySizeY;
        private int _tileDisplaySizeX;
        bool _dataInitialized = false;
        //private int _tileCount;
        //public string[] _internalData = null;
        
        //public List<Tile> Tiles
        //{
        //    get
        //    {
        //        return _tiles;
        //    }
        //}

        public CreamXTileGridComponent()
        {

        }
        
        private void InitData()
        {
            _dataInitialized = true;
            //if (_tileData == null)
            //    _tileData = "";


            ((CreamXTileGrid)SceneObject)._comp = this;
            

            //_tiles = new List<Tile>();

            //_tileCount = TileCountX * TileCountY;
            
            //if (_internalData == null)
            //    _internalData = new string[_tileCount];
            //if (_tileData != string.Empty)
            //{
            //    string[] __vals = _tileData.Split(',');
            //    _internalData = __vals;
            //}
            //else
            //{
            //    for (int x = 0; x < _tileCount; x++)
            //    {
            //        if (_internalData[x] == null)
            //        {
            //            _internalData[x] = "-1";
            //        }
            //    }
            //}
            //if (_internalData.Length != _tileCount)
            //{
            //    //throw new Exception("Invalid TileData");
            //    //fill in gaps
            //    Array.Resize<string>(ref _internalData, _tileCount);
            //    for (int x = 0; x < _tileCount; x++)
            //    {
            //        if (_internalData[x] == null)
            //        {
            //            _internalData[x] = "-1";
            //        }
            //    }
            //}

        }
        
        public override void OnRegister()
        {
            InitData();
            LoadData(true);
            base.OnRegister();
        }
        public void LoadData(bool SplitData)
        {
            
            int __count = 0;
            foreach (TileLayer layer in TileLayers)
            {
                layer.QuadTree = new CreamX.Framework.QuadTree.QuadTree<Tile>(
                    new CreamX.Framework.QuadTree.FRect(
                    SceneObject.Position, new Vector2(
                    SceneObject.Position.X + SceneObject.DisplayWidth,
                    SceneObject.Position.X + SceneObject.DisplayHeight)), 50);

                __count = 0;
                layer.Tiles.Clear();
                string[] _layerData;
                if (SplitData)
                {
                    if (layer.TileData == null || layer.TileData == string.Empty)
                    {
                        for (int y = 0; y < TileCountY; y++)
                        {
                            for (int x = 0; x < TileCountX; x++)
                            {
                                layer.TileData += "-1,";
                            }
                        }
                        layer.TileData = layer.TileData.Substring(0, layer.TileData.Length - 1);
                    }
                    _layerData = layer.TileData.Split(',');
                    layer.InternalData = _layerData;
                }
                else
                {
                    _layerData = layer.InternalData;
                    layer.TileData="";
                    foreach (string s in _layerData)
                    {
                        layer.TileData += s + ",";
                    }
                    layer.TileData = layer.TileData.Substring(0, layer.TileData.Length - 1);
                }

                for (int y = 0; y < _tileCountY; y++)
                {
                    for (int x = 0; x < _tileCountX; x++)
                    {
                        Tile __t = new Tile();
                        __t.TileX = x;
                        __t.TileY = y;
                        __t.Position = new Vector2(x * TileDisplaySizeX, y * TileDisplaySizeY);

                        string s = "-1";
                        
                            s=_layerData[__count];
                        int _tilenum = -1;
                        if (s == null)
                        {
                            s = "-1";
                            _layerData[__count] = "-1";
                        }
                        float rot = 0;
                        if (s.Contains("("))
                        {
                            _tilenum = int.Parse(s.Substring(0, s.IndexOf("(")));
                            rot = float.Parse(s.Substring(s.IndexOf("(") + 1, 1));
                            rot *= MathHelper.ToRadians(90);
                        }
                        else
                            _tilenum = int.Parse(s);

                       // _tileData += s + ",";
                        __t.TileNumber = _tilenum;
                        int tilesx = SceneObject.Material.Texture.Width / TileCutSizeX;
                        int tilesy = SceneObject.Material.Texture.Height / TileCutSizeY;
                        int __tx = (int)tilesx - 1;
                        if (__t.TileNumber > -1)
                        {
                            int X = (int)(__t.TileNumber % tilesx);
                            int Y = (int)((__t.TileNumber - (__t.TileNumber % tilesx)) / tilesx);

                            __t.Rotation = rot;

                            __t.SourceRectangle = new Rectangle(X * TileCutSizeX,
                            Y * TileCutSizeY,
                            TileCutSizeX, TileCutSizeY);

                        }
                        __count++;
                        layer.Tiles.Add(__t);
                        layer.QuadTree.Insert(new CreamX.Framework.QuadTree.QuadTreePositionItem<Tile>(__t, __t.Position, new Vector2(this.TileDisplaySizeX, this.TileDisplaySizeY)));
                    }
                }
            }
            
            
            //if (_tiles == null)
            //    _tiles = new List<Tile>();
            //_tiles.Clear();
            //if (!_dataInitialized)
            //    InitData();

            ////_data = new int[__vals.Length];
            ////for (int i = 0; i < _data.Length; i++)
            ////{
            ////_data[i] = int.Parse(__vals[i]);
            ////}
            //if (_internalData.Length != _tileCountX * _tileCountY)
            //{
            //    Array.Resize<string>(ref _internalData, _tileCountX * _tileCountY);
            //    for (int y = 0; y < _tileCountY; y++)
            //    {
            //        for (int x = 0; x < _tileCountX; x++)
            //        {
            //            _internalData[x * y] = "0";
            //        }
            //    }
            //}
            //int __count = 0;
            //_tileData = "";
            //if (_internalData.Length > 0)
            //{
            //    for (int y = 0; y < _tileCountY; y++)
            //    {
            //        for (int x = 0; x < _tileCountX; x++)
            //        {
            //            Tile __t = new Tile();
            //            __t.TileX = x;
            //            __t.TileY = y;
            //            __t.Position = new Vector2(x * TileDisplaySizeX, y * TileDisplaySizeY);
            //            string s = _internalData[__count];
            //            int _tilenum = -1;
            //            if (s == null)
            //            {
            //                s = "-1";
            //                _internalData[__count] = "-1";
            //            }
            //            float rot = 0;
            //            if (s.Contains("("))
            //            {
            //                _tilenum = int.Parse(s.Substring(0, s.IndexOf("(")));
            //                rot = float.Parse(s.Substring(s.IndexOf("(") + 1, 1));
            //                rot *= MathHelper.ToRadians(90);
            //            }
            //            else
            //                _tilenum = int.Parse(s);

            //            _tileData += s + ",";
            //            __t.TileNumber = _tilenum;
            //            int tilesx = SceneObject.Material.Texture.Width / TileCutSizeX;
            //            int tilesy = SceneObject.Material.Texture.Height / TileCutSizeY;
            //            int __tx = (int)tilesx - 1;
            //            if (__t.TileNumber > -1)
            //            {
            //                int X = (int)(__t.TileNumber % tilesx);
            //                int Y = (int)((__t.TileNumber - (__t.TileNumber % tilesx)) / tilesx);

            //                __t.Rotation = rot;

            //                __t.SourceRectangle = new Rectangle(X * TileCutSizeX,
            //                Y * TileCutSizeY,
            //                TileCutSizeX, TileCutSizeY);

            //            }
            //            __count++;
            //            _tiles.Add(__t);
            //        }
            //    }
            //    _tileData = _tileData.Substring(0, _tileData.Length - 1);
            //}
            ((CreamXTileGrid)this.SceneObject).ReSetGrid();
        }
        
        public override void Update(float elapsed)
        {
            base.Update(elapsed);
        }
        
        public override void OnUnRegister()
        {
            base.OnUnRegister();
        }
       
        [CreamXComponentPropertyAttribute("TileCountX")]
        public int TileCountX
        {
            get { return _tileCountX; }
            set { _tileCountX = value; }
        }

        [CreamXComponentPropertyAttribute("TileDisplaySizeX")]
        public int TileDisplaySizeX
        {
            get { return _tileDisplaySizeX; }
            set { _tileDisplaySizeX = value; }
        }
        
        [CreamXComponentPropertyAttribute("TileDisplaySizeY")]
        public int TileDisplaySizeY
        {
            get { return _tileDisplaySizeY; }
            set { _tileDisplaySizeY = value; }
        }
        
        [CreamXComponentPropertyAttribute("TileCountY")]
        public int TileCountY
        {
            get { return _tileCountY; }
            set { _tileCountY = value; }
        }
        
        [CreamXComponentPropertyAttribute("TileCutSizeX")]
        public int TileCutSizeX
        {
            get { return _tileCutSizeX; }
            set { _tileCutSizeX = value; }
        }
        
        [CreamXComponentPropertyAttribute("TileCutSizeY")]
        public int TileCutSizeY
        {
            get { return _tileCutSizeY; }
            set { _tileCutSizeY = value; }
        }

        //private string _tileData;
        
        //[CreamXComponentPropertyAttribute("TileData")]
        //public string TileData
        //{
        //    get { return _tileData; }
        //    set { _tileData = value; }
        //}

        
        private List<TileLayer> _tileLayer=new List<TileLayer>();
        [CreamXComponentPropertyAttribute("TileLayers")]
        public List<TileLayer> TileLayers
        {
            get { return _tileLayer; }
            set { _tileLayer = value; }
        }


        public void ResetTileLayerData(TileLayer tl)
        {
            tl.Tiles.Clear();
            for (int y = 0; y < TileCountY; y++)
            {
                for (int x = 0; x < TileCountX; x++)
                {
                    tl.TileData += "-1,";
                }
            }
            tl.TileData = tl.TileData.Substring(0, tl.TileData.Length - 1);
            tl.InternalData = tl.TileData.Split(',');
        }
    }
    public class TileLayer
    {
        public QuadTree.QuadTree<Tile> QuadTree;
        private bool _visible;

        public bool Visible
        {
            get { return _visible; }
            set { _visible = value; }
        }

        private int _order;

        public int Order
        {
            get { return _order; }
            set { _order = value; }
        }
        private string _name;

        public string Name
        {
            get { return _name; }
            set { _name = value; }
        }
        public string[] InternalData;
        private string _tileData="";

        public string TileData
        {
            get { return _tileData; }
            set { _tileData = value; }
        }

        public List<Tile> Tiles = new List<Tile>();
        public override string ToString()
        {
            return _name;
        }

        
    }
    [Serializable]
    public class Tile
    {
        public Tile()
        {
        }
        private float _rotation=0;

        public float Rotation
        {
            get { return _rotation; }
            set { _rotation = value; }
        }

        private Rectangle _rectangle;

        public Rectangle SourceRectangle
        {
            get { return _rectangle; }
            set { _rectangle = value; }
        }

        private int _posX;

        public int TileX
        {
            get { return _posX; }
            set { _posX = value; }
        }
        private int _posY;

        public int TileY
        {
            get { return _posY; }
            set { _posY = value; }
        }
        private Vector2 _position;

        public Vector2 Position
        {
            get { return _position; }
            set { _position = value; }
        }

        private int _tileNum;

        public int TileNumber
        {
            get { return _tileNum; }
            set { _tileNum = value; }
        }

        

    }

}
